package org.zjx.analyse;

import lombok.Data;
import lombok.Getter;
import lombok.SneakyThrows;
import org.zjx.common.entity.Font;
import org.zjx.common.entity.ParagraphBean;
import org.zjx.common.entity.Rect;
import org.zjx.indetify.IdentifyFontManager;
import org.zjx.operate.GameMouse;
import org.zjx.resolution.ResolutionAttributes;
import org.zjx.resolution.ResolutionButton;
import org.zjx.task.exception.TaskExecutionException;
import org.zjx.util.ImageUtil;
import org.zjx.window.GameWindow;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

@Data
public class ScreenshotAnalyse {

    private final Rect gameRect;

    @Getter
    public enum OperateType {
        GAME("game"),
        Normal("normal");

        private final String suffix;

        OperateType(String suffix) {
            this.suffix = suffix;
        }
    }

    private final GameWindow gameWindow;
    private OperateType operateType = OperateType.Normal;

    public ScreenshotAnalyse(GameWindow gameWindow) {
        this.gameWindow = gameWindow;
        this.gameRect = gameWindow.getMockBounds();
    }

    //判断鼠标是否在选定区域附近（遮挡，需要离开）
    private boolean mouseInRect(Rect rect) {
        gameWindow.flushGameMouse();
        GameMouse gameMouse = gameWindow.getGameMouse();
        if (gameMouse == null) return false;
        return gameMouse.rect.overlap(rect);
    }

    public Rect conversion(Rect windowArea,Rect rect){
        return new Rect(
                rect.getLeft() + windowArea.getLeft(),
                rect.getTop() + windowArea.getTop(),
                rect.getRight() + windowArea.getLeft(),
                rect.getBottom() + windowArea.getTop()
        );
    }


    public boolean clickResolutionButton(Rect windowArea,ResolutionButton button) {
        boolean buttonOk = true;
        if (button.getPattern() != null) {
            BufferedImage buttonImage = ImageUtil.stringToBufferedImage(button.getPattern());
            List<Point> points = ImageUtil.matchTemplate(gameWindow.getImage(conversion(windowArea,button.getRect())), buttonImage);
            buttonOk = !points.isEmpty();
        }
        if (buttonOk) {
            gameWindow.clickMouse(conversion(windowArea,button.getRect()).getCenter());
            return true;
        } else {
            return false;
        }
    }


    @SneakyThrows
    public String identifyString(Rect windowArea,ResolutionAttributes attributes) {
        List<Font> fonts = IdentifyFontManager.getFonts(attributes.getFontType());
        if (fonts == null || fonts.isEmpty()) throw new TaskExecutionException(attributes.getFontType() + "字库为空");
        BufferedImage image = gameWindow.getImage(conversion(windowArea,attributes.getRect()));
        return IdentifyFontManager.identifyString(image, attributes.getColors(), fonts, attributes.getHeight());
    }

    @SneakyThrows
    public List<ParagraphBean.Word> identify(Rect windowArea,ResolutionAttributes attributes) {
        List<Font> fonts = IdentifyFontManager.getFonts(attributes.getFontType());
        if (fonts == null || fonts.isEmpty()) throw new TaskExecutionException(attributes.getFontType() + "字库为空");
        BufferedImage image = gameWindow.getImage(conversion(windowArea,attributes.getRect()));
        return IdentifyFontManager.identify(image, attributes.getColors(), fonts, attributes.getHeight());
    }


    public boolean haveResolutionButton(Rect windowArea,ResolutionButton button) {
        if (mouseInRect(conversion(windowArea,button.getRect()))) mouseAloofRect(conversion(windowArea,button.getRect()));
        BufferedImage buttonImage = ImageUtil.stringToBufferedImage(button.getPattern());
        List<Point> points = ImageUtil.matchTemplate(gameWindow.getImage(conversion(windowArea,button.getRect())), buttonImage);
        return !points.isEmpty();
    }

    public boolean haveColors(Rect windowArea,Rect rect, List<Color> colors) {
        // 1. 获取指定区域的图像
        BufferedImage image = gameWindow.getImage(conversion(windowArea,rect));
        if (image == null) {
            return false;
        }

        // 2. 获取图像的宽度和高度
        int width = image.getWidth();
        int height = image.getHeight();

        // 3. 遍历图像中的每个像素
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 4. 获取当前像素的颜色
                int pixel = image.getRGB(x, y);
                Color pixelColor = new Color(pixel, true); // 包含alpha通道

                // 5. 检查当前像素颜色是否在目标颜色列表中
                for (Color targetColor : colors) {
                    if (colorsMatch(pixelColor, targetColor)) {
                        return true; // 找到匹配颜色
                    }
                }
            }
        }

        // 6. 遍历完所有像素未找到匹配颜色
        return false;
    }

    /**
     * 比较两个颜色是否匹配（可自定义匹配规则）
     */
    private boolean colorsMatch(Color color1, Color color2) {
        // 简单比较RGB值（忽略Alpha通道）
        return color1.getRed() == color2.getRed() &&
                color1.getGreen() == color2.getGreen() &&
                color1.getBlue() == color2.getBlue();

        // 如果需要考虑颜色容差，可以使用如下方式：
        // int tolerance = 10; // 容差范围
        // return Math.abs(color1.getRed() - color2.getRed()) <= tolerance &&
        //        Math.abs(color1.getGreen() - color2.getGreen()) <= tolerance &&
        //        Math.abs(color1.getBlue() - color2.getBlue()) <= tolerance;
    }

    //让鼠标离开选定区域
    public void mouseAloofRect(Rect rect) {
        final int MAX_ATTEMPTS = 3;
        final int DELAY_MS = 30;
        int attempts = 0;

        do {
            if (!mouseInRect(rect)) return;

            Point safePoint = findLargestRemainingAreaCenter(rect);

            GameMouse beforeMove = gameWindow.getGameMouse();
            gameWindow.getGameOperate().moveMouse(safePoint.x, safePoint.y);
            gameWindow.delay(DELAY_MS);
            gameWindow.flush();
            // 如果鼠标位置没变，增加尝试计数
            if (beforeMove.equals(gameWindow.getGameMouse())) {
                attempts++;
            } else {
                attempts = 0; // 重置计数器
            }

        } while (attempts < MAX_ATTEMPTS);

        throw new RuntimeException("无法将鼠标移出区域，最大尝试次数已达");
    }

    //除开给定区域rect之外的矩形区域中心点
    private Point findLargestRemainingAreaCenter(Rect rect) {
        // 确保rect在trueGameRect范围内
        int rectLeft = Math.max(rect.getLeft(), gameRect.getLeft());
        int rectRight = Math.min(rect.getRight(), gameRect.getRight());
        int rectTop = Math.max(rect.getTop(), gameRect.getTop());
        int rectBottom = Math.min(rect.getBottom(), gameRect.getBottom());

        // 计算有效剩余区域
        Rect[] candidates = {
                new Rect(gameRect.getLeft(), gameRect.getTop(), rectLeft, gameRect.getBottom()),    // 左
                new Rect(rectRight, gameRect.getTop(), gameRect.getRight(), gameRect.getBottom()),  // 右
                new Rect(rectLeft, gameRect.getTop(), rectRight, rectTop),                       // 上
                new Rect(rectLeft, rectBottom, rectRight, gameRect.getBottom())                  // 下
        };

        // 过滤掉无效区域（宽度或高度<=0）
        Rect largest = Arrays.stream(candidates)
                .filter(r -> r.getWidth() > 0 && r.getHeight() > 0)
                .max(Comparator.comparingInt(r -> r.getWidth() * r.getHeight()))
                .orElse(gameRect); // 默认回退

        return largest.getCenter();
    }

}
